package cc.imos.repository;

import cc.imos.communal.entity.Page;
import cc.imos.entity.SysAccount;
import cc.imos.entity.SysAccountLine;
import cc.imos.medium.AccountPageArgs;
import cc.imos.medium.LoginArgs;
import com.google.common.collect.Lists;
import com.xiaoleilu.hutool.util.PageUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 *
 * Created by asher on 2017/4/23.
 */
@Repository
@CacheConfig(cacheNames = {"SystemAccountRepository"})
public class SystemAccountRepository {

    @Autowired
    private NamedParameterJdbcTemplate npJdbcTemplate;


    // @Transactional(readOnly = true)
    public SysAccount findForLogin(LoginArgs loginArgs) {
        loginArgs.setFlag(true);
        String sql = "SELECT * FROM sys_account WHERE keyword = :keyword AND password = :password AND flag = :flag";
        return npJdbcTemplate.queryForObject(sql, new BeanPropertySqlParameterSource(loginArgs), BeanPropertyRowMapper.newInstance(SysAccount.class));
    }

    @Transactional()
    public void insertLine(SysAccountLine sysAccountLine) {
        sysAccountLine.setCreateTime(new Date());
        sysAccountLine.setFlag(true);

        SqlParameterSource sqlParameterSource = new BeanPropertySqlParameterSource(sysAccountLine);

        // 修改相同在线类型为无效
        String deleteSql = "UPDATE sys_account_line SET flag = FALSE WHERE account_id = :accountId AND line_mold = :lineMold";
        npJdbcTemplate.update(deleteSql, sqlParameterSource);

        // 插入新的在线信息
        String insertSql = "INSERT INTO sys_account_line" +
                "(access_token, access_key, expires_time, account_id, line_mold, create_time, flag) " +
                "VALUES " +
                "(:accessToken, :accessKey, :expiresTime, :accountId, :lineMold, :createTime, :flag)";
        npJdbcTemplate.update(insertSql, sqlParameterSource);
    }

    public void logout(SysAccountLine sysAccountLine) {
        String sql = "DELETE FROM sys_account_line WHERE access_token = :accessToken";
        npJdbcTemplate.update(sql, new BeanPropertySqlParameterSource(sysAccountLine));
    }

    public Page<SysAccount> page(AccountPageArgs args) {
        String totalRowSql = "SELECT COUNT(*)";
        String pageRowSql = "SELECT *";

        String queryWhereSql = " FROM sys_account";

        if(StringUtils.hasText(args.getKeyword())) {
            args.setKeyword("%"+ args.getKeyword() +"%");
            queryWhereSql += " AND keyword LIKE :keyword";
        }

        if(Objects.nonNull(args.getFlag())) {
            queryWhereSql += " AND flag = :flag";
        }
        totalRowSql += queryWhereSql;
        int totalRow = npJdbcTemplate.queryForObject(totalRowSql, new BeanPropertySqlParameterSource(args), BeanPropertyRowMapper.newInstance(Integer.class));

        if(totalRow > 0) {
            pageRowSql += queryWhereSql;
            if(args.getPageNumber() < 1)
                args.setPageNumber(1);
            int totalPage = PageUtil.totalPage(totalRow, args.getPageSize());
            if(args.getPageNumber() > totalPage) {
                args.setPageNumber(totalPage);
            }
            args.setPageNumber(args.getPageNumber() - 1);

            pageRowSql += " LIMIT :pageNumber, :pageSize";

            List<SysAccount> pageList = npJdbcTemplate.queryForList(pageRowSql, new BeanPropertySqlParameterSource(args), SysAccount.class);

            return new Page<>(pageList, args.getPageNumber() + 1, args.getPageSize(), totalRow);
        } else {
            return new Page<>();
        }
    }

    // @CacheEvict(cacheNames = {"SystemAccountRepository"})
    public long insert( Map<String, Object> args) {
        return 1L;
    }


    //    @Cacheable
    public List<Map<String, Object>> listRole(Map<String, Object> args) {
        return null;
    }

}
